﻿using OnlineSoccerManager.Classes;
using OnlineSoccerManager.Helper;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Xml;

namespace OnlineSoccerManager
{
    public class WebClient
    {
        private readonly string resourcePath = "resources/";


        private Regex loginSuccess = new Regex(@"href='soccer.php\?PHPSESSID=(?<sessionid>\S+)'");
        private Regex playerEntry = new Regex(@"<td align=left>\s*<a href=javascript:Spieler\(.(?<SessionID>\w*).,(?<ID>\d*)\)>\s*(?<Name>[\w\s]+)\s*</a>\s*</td>\s*<td>\s*(?<Position>\w*)\s*</td>\s*<td>\s*(?<Age>\d*)\s*</td>\s*<td>\s*(?<Strength>\d*)\s*</td>\s*<td>\s*(?<SingleStrength>\d*)\s*</td>\s*<td>\s*<img[\w\s\'=:]+src='flagge/(?<Country>\d*)\.png'[\w\s\'=:]*>\s*</td>\s*<td>\s*<img[\w\s\'=:]*src='images/schuh(?<EWSID>\d*)\.gif'[\w\s\'=:]*title='(?<EWS>\w*)'[\w\s\'=:]*></td><td align='right'>(?<Value>[\.\d]*)\s*KSM\$</td><td><a href='mannschaft_kader_spieler.php\?art=tmauf&PHPSESSID=\w*&kid=\d*'><img src='images/\w*\.gif'[\w\s\'=:]*></a></td><td align='right'>(?<Treaty>\d*)\s*ZAT</td></tr>");
        private Regex playerSkills = new Regex(@"<td[\w\s\'=:]+>Widerstandskraft:</td>[\w\s]*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<ResistanceChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Resistance>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*></td><td[\w\s\'=:]*></td><td[\w\s\'=:]*>Zuverl&auml;ssigkeit:</td>[\w\s]*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]+title='(?<ReliabilityChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Reliability>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*>St&auml;rke:</td><td[\w\s\'=:]*>(?<strength>\d+)[&nbsp;\s]*</td><td[\w\s\'=:]*>Schuss:</td>[\w\s]*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<KickChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Kick>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*>einSt&auml;rke:</td><td[\w\s\'=:]*>(?<singleStrength>\d+)[&nbsp;\s]*</td><td[\w\s\'=:]*>Passen:</td>[\w\s]*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<PassChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Pass>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*></td><td[\w\s\'=:]*></td><td[\w\s\'=:]*>Kopfball:</td>[\w\s]*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<HeaderChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Header>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*>Kondition:</td><td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<EnduranceChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Endurance>[\d,\-+]+)[&nbsp;\s]*</td><td[\w\s\'=:]*>Zweikampf:</td>.*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<DuelChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Duel>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*>Fitness:</td><td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<FitnessChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Fitness>[\d,\-+]+)[&nbsp;\s]*</td><td[\w\s\'=:]*>Ballkontrolle:</td>.*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<BallControlChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<BallControl>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*>Moral:</td><td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<MoraleChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Morale>[\d,\-+]+)[&nbsp;\s]*</td><td[\w\s\'=:]*>Geschwindigkeit:</td>.*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<VelocityChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Velocity>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*></td><td[\w\s\'=:]*></td><td[\w\s\'=:]*>&Uuml;bersicht:</td>[\w\s]*<td class='tabc1'>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<SurveyChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Survey>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*>Gesamt-Skills:</td><td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='[\d,\-+]*'>[&nbsp;\s]*){0,1}[\w\s]*</td>[\w\s]*<td[\w\s\'=:]*>(?<total>[\d,\-+]+)[&nbsp;\s]*</td><td[\w\s\'=:]*>Deckungsarbeit:</td>.*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<CoveringChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Covering>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*></td><td[\w\s\'=:]*></td><td[\w\s\'=:]*>Aggressivit&auml;t:</td>[\w\s]*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<AggressivityChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Aggressivity>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*
<tr><td[\w\s\'=:]*></td><td[\w\s\'=:]*></td><td[\w\s\'=:]*>Disziplin:</td>[\w\s]*<td[\w\s\'=:]*>(<img src='images/\w+\.gif'[\w\s\'=:]*title='(?<DisciplineChange>[\d,\-+]*)'>[&nbsp;\s]*){0,1}[\w\s]*</td><td[\w\s\'=:]*>(?<Discipline>[\d,\-+]+)[&nbsp;\s]*</td></tr>\w*", RegexOptions.Multiline);

        private Dictionary<string, Bitmap> imageCache = new Dictionary<string, Bitmap>();

        private HttpRequest request;


        public WebClient()
        {
            this.request = new HttpRequest();
        }

        public string SessionID { get; set; }
        public string BaseUrl {
            get
            {
                return this.request.UrlBase;
            }
            set
            {
                this.request.UrlBase = value;
            }
        }


        /// <summary>
        /// Synchronously logs in...
        /// </summary>
        /// <param name="username">username</param>
        /// <param name="Password">Password</param>
        /// <returns>true if login succeeded otherwise false</returns>
        public bool Login(string username, string Password)
        {
            

            Dictionary<string, string> data = new Dictionary<string,string>();
            data["name"] = username;
            data["pass"] = Password;
            string doc = request.PostFormular("login.php", data);
            if (doc == null)
                return false;
            
            Match match = loginSuccess.Match(doc);
            if (match.Success)
                this.SessionID = match.Groups["sessionid"] == null ? null : match.Groups["sessionid"].Value;

            if (this.SessionID != null)
                return true;

            return false;
        }

        public List<Player> GetTeam()
        {
            if (this.SessionID == null)
                return null;

            List<Player> players = new List<Player>();

            Dictionary<string, string> data = new Dictionary<string, string>();
            data["art"] = "profi";
            data["PHPSESSID"] = this.SessionID;

            string doc = this.request.GetPage("mannschaft_kader_team.php", data);
            if (doc == null)
                return null;

            MatchCollection matches = playerEntry.Matches(doc);

            foreach (Match match in matches)
            {
                Player player = new Player();
                player.ID = match.Groups["ID"] == null ? -1 : match.Groups["ID"].Value.ParseInt();
                player.Name = match.Groups["Name"] == null ? null : match.Groups["Name"].Value;
                player.Age = match.Groups["Age"] == null ? -1 : match.Groups["Age"].Value.ParseInt();
                player.Position = match.Groups["Position"] == null ? null : match.Groups["Position"].Value;
                player.Strength = match.Groups["Strength"] == null ? -1 : match.Groups["Strength"].Value.ParseInt();
                player.SingleStrength = match.Groups["SingleStrength"] == null ? -1 : match.Groups["SingleStrength"].Value.ParseInt();
                player.Country = match.Groups["Country"] == null ? -1 : match.Groups["Country"].Value.ParseInt();
                player.EWS = match.Groups["EWS"] == null ? null : match.Groups["EWS"].Value;
                player.EWSID = match.Groups["EWSID"] == null ? -1 : match.Groups["EWSID"].Value.ParseInt();
                player.Value = match.Groups["Value"] == null ? -1 : match.Groups["Value"].Value.ParseInt();
                player.Treaty = match.Groups["Treaty"] == null ? -1 : match.Groups["Treaty"].Value.ParseInt();
                players.Add(player);

                // load flag images
                string flag = "flagge/" + player.Country + ".png";
                player.FlagImage = this.LoadImage(flag);
                
                // load ews images
                string EWS = "images/schuh" + player.EWSID + ".gif";
                player.EWSImage = this.LoadImage(EWS);

                player.Skill = this.LoadSkills(player.ID);

                player.Skill.Technical.ChangeUpImage = this.LoadImage("images/plus.gif");
                player.Skill.Technical.ChangeDownImage = this.LoadImage("images/minus.gif");
                player.Skill.Common.ChangeUpImage = this.LoadImage("images/plus.gif");
                player.Skill.Common.ChangeDownImage = this.LoadImage("images/minus.gif");
               

            }

            if (players.Count == 0)
                return null;

            return players;
            
        }

        private Skills LoadSkills(int playerId)
        {
            // load details
            Skills skill = new Skills();
            TechnicalSkills technical = new TechnicalSkills();
            CommonSkills common = new CommonSkills();
            skill.Common = common;
            skill.Technical = technical;

            Dictionary<string, string> param = new Dictionary<string, string>();
            param["id"] = playerId.ToString();
            param["action"] = "0";
            string details = this.request.GetPage("div/dspieler.php", param);

            if (details == null)
                return skill;

            Match match = this.playerSkills.Match(details);
            if (match.Success)
            {
                technical.Aggressivity = match.Groups["Aggressivity"] == null ? null : match.Groups["Aggressivity"].Value.ParseDecimal();
                technical.BallControl = match.Groups["BallControl"] == null ? null : match.Groups["BallControl"].Value.ParseDecimal();
                technical.Covering = match.Groups["Covering"] == null ? null : match.Groups["Covering"].Value.ParseDecimal();
                technical.Discipline = match.Groups["Discipline"] == null ? null : match.Groups["Discipline"].Value.ParseDecimal();
                technical.Duel = match.Groups["Duel"] == null ? null : match.Groups["Duel"].Value.ParseDecimal();
                technical.Header = match.Groups["Header"] == null ? null : match.Groups["Header"].Value.ParseDecimal();
                technical.Kick = match.Groups["Kick"] == null ? null : match.Groups["Kick"].Value.ParseDecimal();
                technical.Pass = match.Groups["Pass"] == null ? null : match.Groups["Pass"].Value.ParseDecimal();
                technical.Reliability = match.Groups["Reliability"] == null ? null : match.Groups["Reliability"].Value.ParseDecimal();
                technical.Resistance = match.Groups["Resistance"] == null ? null : match.Groups["Resistance"].Value.ParseDecimal();
                technical.Survey = match.Groups["Survey"] == null ? null : match.Groups["Survey"].Value.ParseDecimal();
                technical.Velocity = match.Groups["Velocity"] == null ? null : match.Groups["Velocity"].Value.ParseDecimal();

                technical.AggressivityChange = match.Groups["AggressivityChange"] == null ? null : match.Groups["AggressivityChange"].Value.ParseDecimal();
                technical.BallControlChange = match.Groups["BallControlChange"] == null ? null : match.Groups["BallControlChange"].Value.ParseDecimal();
                technical.CoveringChange = match.Groups["CoveringChange"] == null ? null : match.Groups["CoveringChange"].Value.ParseDecimal();
                technical.DisciplineChange = match.Groups["DisciplineChange"] == null ? null : match.Groups["DisciplineChange"].Value.ParseDecimal();
                technical.DuelChange = match.Groups["DuelChange"] == null ? null : match.Groups["DuelChange"].Value.ParseDecimal();
                technical.HeaderChange = match.Groups["HeaderChange"] == null ? null : match.Groups["HeaderChange"].Value.ParseDecimal();
                technical.KickChange = match.Groups["KickChange"] == null ? null : match.Groups["KickChange"].Value.ParseDecimal();
                technical.PassChange = match.Groups["PassChange"] == null ? null : match.Groups["PassChange"].Value.ParseDecimal();
                technical.ReliabilityChange = match.Groups["ReliabilityChange"] == null ? null : match.Groups["ReliabilityChange"].Value.ParseDecimal();
                technical.ResistanceChange = match.Groups["ResistanceChange"] == null ? null : match.Groups["ResistanceChange"].Value.ParseDecimal();
                technical.SurveyChange = match.Groups["SurveyChange"] == null ? null : match.Groups["SurveyChange"].Value.ParseDecimal();
                technical.VelocityChange = match.Groups["VelocityChange"] == null ? null : match.Groups["VelocityChange"].Value.ParseDecimal();

                common.Endurance = match.Groups["Endurance"] == null ? null : match.Groups["Endurance"].Value.ParseDecimal();
                common.Fitness = match.Groups["Fitness"] == null ? null : match.Groups["Fitness"].Value.ParseDecimal();
                common.Morale = match.Groups["Morale"] == null ? null : match.Groups["Morale"].Value.ParseDecimal();

                common.EnduranceChange = match.Groups["EnduranceChange"] == null ? null : match.Groups["EnduranceChange"].Value.ParseDecimal();
                common.FitnessChange = match.Groups["FitnessChange"] == null ? null : match.Groups["FitnessChange"].Value.ParseDecimal();
                common.MoraleChange = match.Groups["MoraleChange"] == null ? null : match.Groups["MoraleChange"].Value.ParseDecimal();

                skill.Technical = technical;
                skill.Common = common;

            }
            return skill;
        }

        private Bitmap LoadImage(string name)
        {
            if (this.imageCache.ContainsKey(name))
                return this.imageCache[name];

            string path = this.resourcePath + name;
            
            Bitmap image = null;
            if (File.Exists(path)) {
                // load picture from local resource folder
                image = Bitmap.FromFile(path) as Bitmap;
            } else {
                // load picture from webserver
                image = this.request.GetImage(name);
                if (image == null)
                    return null;

                // create directories if nessessary
                if (!Directory.Exists(Path.GetDirectoryName(path)))
                    Directory.CreateDirectory(Path.GetDirectoryName(path));

                // save picture
                image.Save(path);
            }

            this.imageCache[name] = image;

            return image;
        }
    }
}
